<?php
/**
 *
 *
 * @author Zeon <scplay@gmail.com>
 * @date 2018/11/13 14:47
 * @copyright PanxSoft Inc.
 */

namespace App\Http\Controllers\Api\V1\App\Common;


use App\Exceptions\ApiErrCode;
use App\Http\Controllers\ApiController;

use App\Http\Requests\Common\SmsProxyRequest;
use App\Http\Requests\Common\TelephoneRequest;
use App\Models\Customers\Customer;
use App\Models\Setting;
use App\Services\Common\VerifyCodeService;
use App\Services\EasySms\AliSMSCountry;
use App\Services\EasySms\EasySmsService;
use Illuminate\Http\Request;
use Illuminate\Validation\Validator;
use Overtrue\EasySms\Exceptions\NoGatewayAvailableException;


class SendPhoneVerifyCodeController extends ApiController
{

    const MINUTES = 5;
    const DEFAULT_COUNTRY_CODE = 86; // 中国的国家区号

    private $easySmsService;
    private $phoneVerifyCodeService;

    public function __construct(EasySmsService $easySmsService, VerifyCodeService $phoneVerifyCodeService)
    {
        $this->easySmsService = $easySmsService;
        $this->phoneVerifyCodeService = $phoneVerifyCodeService;
    }

    /**
     *  返回国家的电话区号
     *
     * @return array|\Illuminate\Http\Response
     */
    public function countryCode()
    {
        $default_country_code = Setting::getSettingSpecifyValue('config_sms_country_code');
        $country_codes = AliSMSCountry::codes();

        $country_codes = AliSMSCountry::transByLocale($country_codes);

        return $this->response(compact('default_country_code', 'country_codes'));
    }

    /**
     * 发送注册验证码
     * @param TelephoneRequest $request
     *
     * @return array|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function send(TelephoneRequest $request)
    {
        $dial_code = (int)$request->dial_code ?: EasySmsService::COUNTRY_CODE_CN;
        $telephone = $request->telephone;

        $this->checkUnless($this->isTelephoneExist($telephone, $dial_code), trans('customer.phone_exist'));

        // 国际号码需要加区号
        $verify_code = $this->phoneVerifyCodeService->generate();
        $cache_key = $this->phoneVerifyCodeService->getRegisterCacheKey($telephone, $dial_code);
        $this->phoneVerifyCodeService->cacheVerifyCode($cache_key, $verify_code);

        $send = $this->easySmsService->registerSend($telephone, $verify_code, $dial_code);

        if (config('app.debug')) {
            $debug_verify_code = $verify_code;
        }

        return $this->response(compact('send', 'debug_verify_code'));
    }

    /**
     * 发送重置密码的验证码
     * @param TelephoneRequest $request
     *
     * @return array|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function resetPwdSend(TelephoneRequest $request)
    {
        $dial_code = (int)$request->dial_code ?: EasySmsService::COUNTRY_CODE_CN;
        $phone = $request->telephone;

        $this->checkIsTrue($this->isTelephoneExist($phone, $dial_code), trans('customer.phone_not_exist'));

        $verify_code = $this->phoneVerifyCodeService->generate();
        $cache_key = $this->phoneVerifyCodeService->getResetPwdCacheKey($phone, $dial_code);
        $this->phoneVerifyCodeService->cacheVerifyCode($cache_key, $verify_code);

        $send = $this->easySmsService->resetPwdSend($phone, $verify_code, $dial_code);

        if (config('app.debug')) {
            $debug_verify_code = $verify_code;
        }

        return $this->response(compact('send', 'debug_verify_code'));
    }

    /**
     * @param string $telephone
     * @param int $dial_code
     *
     * @return bool
     */
    private function isTelephoneExist(string $telephone, int $dial_code): bool
    {
        return (new Customer)->where('telephone', $telephone)->where('dial_code', $dial_code)->exists();
    }

    /**
     * @param SmsProxyRequest $request
     *
     * @return array
     * @throws \Exception
     */
    public function smsProxy(SmsProxyRequest $request)
    {
        try {
            return $this->easySmsService->send(
                $request->sign, $request->to, json_decode($request->message, true)
            );
        } catch (NoGatewayAvailableException $exception) {
            $exception = $exception->getException('aliyun');

            $this->checkFailed(trans('service.sms_failed_to_send', [
                'tip' => $exception->getMessage()
            ]), ApiErrCode::SMS_SEND_FAILED);
        } catch (\Exception $exception) {
            $this->checkFailed($exception->getMessage(), ApiErrCode::SMS_SEND_FAILED);
        }
    }
}